using System;
using System.Runtime.Serialization;

namespace Copperline.Escriba
{
	/// <summary>
	/// Represents the severity of a log event
	/// </summary>
	/// <remarks>The severity of a log event dictates whether the event is
	/// handled or ignored by loggers.
	/// </remarks>
	public enum ESeverity 
	{
		/// <summary>lowest severity</summary>
		debug = 0,
		/// <summary>information</summary>
		info = 1,
		/// <summary>important</summary>
		notice = 2,
		/// <summary>warning</summary>
		warning = 3,
		/// <summary>error</summary>
		error = 4,
		/// <summary>highest severity</summary>
		fatal = 5
	};

	/// <summary>
	/// Data structure encapsulating a log event.
	/// </summary>
	[Serializable()]
	public class LogEntry
	{

		/// <summary>
		/// default severity label for <c>LogEntry.debug</c> severity
		/// </summary>
		public const string DEBUG = "[D]";

		/// <summary>
		/// default severity label for <c>LogEntry.info</c> severity
		/// </summary>
		public const string INFO = "[I]";

		/// <summary>
		/// default severity label for <c>LogEntry.notice</c> severity
		/// </summary>
		public const string NOTICE = "[N]";

		/// <summary>
		/// default severity label for <c>LogEntry.warning</c> severity
		/// </summary>
		public const string WARN = "[W]";

		/// <summary>
		/// default severity label for <c>LogEntry.error</c> severity
		/// </summary>
		public const string ERROR = "[E]";

		/// <summary>
		/// default severity label for <c>LogEntry.fatal</c> severity
		/// </summary>
		public const string FATAL = "[F]";

		private static string[] aSeverity = { DEBUG, INFO, NOTICE, WARN, ERROR, FATAL };

		/// <summary>
		/// default date format, corresponding to full date and time
		/// </summary>
		public static string TimeStampFormat
		{
			get { return "{0:yyyy-MM-dd HH:mm:ss}"; }
		}

		/// <summary>
		/// default severity format
		/// </summary>
		public static string SeverityFormat
		{
			get { return "{0}"; }
		}

		private DateTime timeStamp;
		/// <summary>
		/// The time that <c>this</c> entry was created.
		/// </summary>
		public DateTime TimeStamp { get { return this.timeStamp; } }

		private string entry;
		/// <summary>
		/// The message representing the log entry.
		/// </summary>
		public string Entry	{ get { return this.entry; } }

		private ESeverity severity;
		/// <summary>
		/// The severity of <c>this</c> log entry
		/// <seealso cref="ESeverity"/>
		/// </summary>
		public ESeverity Severity { get { return this.severity; } }

		/// <summary>
		/// Returns the mapped (abbreviated) name for the severity
		/// </summary>
		public string SeverityName { get { return aSeverity[ (int)Severity ]; } }

		/// <summary>
		/// Sets the text string to represent a severity level in the log
		/// </summary>
		/// <param name="severity">the severity enumeration whose name is being set
		/// <see cref="ESeverity"/></param>
		/// <param name="sName">the name for the given severity enumerated type</param>
		public static void SetSeverityName( ESeverity severity, string sName  )
		{
			aSeverity.SetValue( sName, (int)severity );
		}

		/// <summary>
		/// Returns the text string that represents a severity enumeration
		/// </summary>
		/// <param name="severity">the severity enumeration whose text
		/// name will be returned</param>
		/// <returns>the string representing the severity enumeration</returns>
		public static string GetSeverityName( ESeverity severity )
		{
			return (string)aSeverity.GetValue( (int)severity );
		}

		/// <summary>
		/// Copy constructor for the <c>LogEntry</c> class.
		/// </summary>
		/// <param name="le">The log entry to copy</param>
		public LogEntry( LogEntry le )
		{
			Init( le.entry, le.severity );
		}

		/// <summary>
		/// Creates a new instance of the <c>LogEntry</c> class with
		/// the current time and <c>debug</c> severity.
		/// </summary>
		/// <param name="entry">the message intended for logging.</param>
		public LogEntry( string entry )
		{
			Init( entry, ESeverity.debug );
		}

		/// <summary>
		/// Creates a new instance of the <c>LogEntry</c> class.
		/// </summary>
		/// <param name="entry">the message intended for logging.</param>
		/// <param name="severity">the severity of the log entry.
		/// <seealso cref="ESeverity"/></param>
		public LogEntry( string entry, ESeverity severity )
		{
			Init( entry, severity );
		}

		private void Init( string entry, ESeverity severity )
		{
			timeStamp = DateTime.Now;
			this.entry = entry;
			this.severity = severity;
		}
	}
}
